home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- Program: NOBRAIN
- Author: Carl Fussell
- Santa Clara Univ
- CARL@SCU.BITNET
- Date: April 1988
- Descript: Program "cures" diskettes infected with the "Brain" virus.
- Only works for DSDD diskettes (though could be easily
- modified). But that is all Brain appears to infect at this
- point.
- Language: Computer Innovations CI86 C Language
- Operation: Run it by typing: x> NOBRAIN DRV: [0/1]
- where DRV: is the drive containing the "infected" diskette.
- The option 0 or 1 is for verbose mode where it dumps contents
- of infected sectors, steps being performed, etc. to display.
- If specified and non-zero, verbose occurs.
-
- The program first checks to see if the machine itself is
- infected. If so, you are asked if you want the machine
- "cleansed". If yes, it is and the program proceeds. If no,
- the program aborts. You cannot leave the machine infected
- but proceed with curing the diskettes.
-
- The program will abort at any time it thinks it has found an
- inconsistancy, ie. some portion that does NOT appear to be
- infected. The diskette must be "fully infected" before cure will
- take place. If it thinks the diskette IS fully infected, then
- just before the cure is effected, a confirmation will be asked for.
- You can leave the diskette infected if desired.
- DISCLAIMER:
- I claim no responsibility whatsoever for any havoc, damage,
- data loss, or anything else that results from the running of
- this program. You use it AT YOUR OWN RISK!! I wrote it to
- solve a problem at our site but make absolutely no guarantee
- (implied or otherwise) as to its operation. Neither does
- Santa Clara University in any way endorse or support the
- use of this program nor does it assume any responsibility
- for any consequences resulting from the running of this
- program.
- ****************************************************************/
- #include <stdio.h>
-
- /* Error Message Definitions */
- #define noarg 1
- #define invadr 2
- #define nofixd 3
-
- /* Misc Definitions */
- #define byte unsigned char
- #define word unsigned int
-
- /* Global Definitions */
- struct regval { unsigned ax,bx,cx,dx,si,di,ds,es; };
- struct segval { unsigned scs,sss,sds,ses; } segs;
- struct {
- byte junk1[3];
- char sysid[8];
- word sectsize;
- byte clustsize;
- word resvsects;
- byte FATcopies;
- word rootdirentries;
- word totalsects;
- byte idbyte;
- word FATsects;
- word trksects;
- word heads;
- word resvspecial;
- byte remainder[4*512-30]; } bootinfo;
-
- struct direntry {
- char fname[8];
- char ext[3];
- byte attrib;
- byte resvd[10];
- word xtime;
- word xdate;
- word startFAT;
- long fsize; };
-
- struct regval rreg,sreg;
- struct direntry directory[1024];
- int drv;
- unsigned char FAT[10*512]; /* allow for 10 sectors though only 4 */
- /* are needed for D-9 diskettes */
-
- /* Function Definitions */
- int copyvec();
- int checkvec();
- word gettime();
- word getdate();
- int findlabel();
- int changelabel();
- int getFATentry();
- int setFATentry();
- int dlstoclus();
- int infected();
- int errorout();
- int diskerror();
- int diskread();
- int bdiskread();
- int diskwrite();
- int bdiskwrite();
- int displayraw();
- int homecursor();
- int clearscreen();
-
- /************************************************************/
- /* Main Program Starts Here */
- /************************************************************/
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int idbyte,sect,i,nsects,done=0,dirsize,dirstart,pc_infected;
- unsigned int *p,bogus_clus,f1,f2,f3;
- char drvlet, ans[20];
- unsigned char bufr[1024],bootrec[512],orig_bootrec[512],virus[6*512];
- int bogus_trk,bogus_sect,bogus_side,bogus_dls,bogus_label,dispflag;
-
- if (argc<2) {
- printf(" This program is used to eradicate the Brain virus.\n");
- printf(" Usage: NOBRAIN drive:\n\n");
- printf(" Where drive is the disk drive containing the
- infected diskette.\n\n");
- printf(" Warning: Probably should use this on a healthy diskette.
- It may\n");
- printf(" well corrupt the good diskette!\n\n");
- exit();
- } else {
- drvlet = *argv[1];
- drv = toupper(drvlet) - 'A' + 1; /* A=1, B=2 */
- if (drv<1 || drv>2) {
- printf(" Error: Only drive A: or B: may be specified!\n");
- exit();
- }
- dispflag = (argc>2);
- }
-
- clearscreen();
- if (pc_infected=checkvec(0x13)) {
- printf("\nWARNING! This machine has itself been infected and thus\n");
- printf(" so has the \"cure\" diskette in all likelihood.\n");
- printf(" You can proceed but will probably need to
- inoculate\n");
- printf(" the \"cure\" diskette too.\7\n");
- printf("\n VACCINATE machine itself (Y/N) ?");
- scanf("%s",ans);
- if (toupper(ans[0])=='Y') {
- printf("\n Inoculating the PC...\n");
- copyvec(0x6D,0x13);
- } else {
- printf("\n Cannot \"cure\" diskettes on an infected machine...");
- printf("\n Aborting cure....\n");
- exit();
- } /* else */
- } /* if */
- printf("\n\nAttempting cure on Drive %c:.... :-)\n",'A'+drv-1);
- /* Get boot record */
- if (dispflag) printf("\nGetting Boot Record...\n");
- diskread(drv,0,1,bootrec) ;
- if (dispflag) displayraw(bootrec,1);
- if (!infected(bootrec,0x30,"\(c\) 1986 Brain")) {
- printf("\nBoot Record Check:\n");
- printf("\n This does not appear to be a \"Brain\" infected
- diskette.\n");
- printf("\n Aborting cure...\n");
- exit();
- }
- /* extra confirmation on signature */
- p = &bootrec[4];
- if (*p != 0x1234) {
- printf("\nBoot Record Signature Check:\n");
- printf("\n This does not appear to be a \"Brain\" infected
- diskette.\n");
- printf("\n Aborting cure...\n");
- exit();
- }
-
- bogus_side = bootrec[6];
- bogus_sect = bootrec[7];
- bogus_trk = bootrec[8];
- bogus_dls = bogus_trk*9*2 + bogus_side*9 + bogus_sect;
-
- /* Get virus sectors */
- if (dispflag) printf("\nGetting virus records...\n");
- diskread(drv,bogus_dls,5,virus);
- if (!infected(virus,342,"\(c\) 1986 Brain")) {
- printf("\nVirus Check:\n");
- printf("\n This does not appear to be a \"Brain\" infected
- diskette.\n");
- printf("\n Aborting cure...\n");
- exit();
- }
- if (dispflag) displayraw(virus,5);
-
- /* Get original Boot record */
- if (dispflag) printf("\nGetting original boot record...\n");
- diskread(drv,bogus_dls-1,1,orig_bootrec) ;
- if (!infected(orig_bootrec,3,"IBM ")) {
- printf("\n This appears to be a partially infected \"Brain\" diskette
- but\n");
- printf(" without a \"healthy\" saved boot record was not found.\n");
- printf("\n Aborting cure...\n");
- exit();
- }
- if (dispflag) displayraw(orig_bootrec,1);
-
- /* Get FAT table read in */
- if (dispflag) printf("\nGetting FAT table...\n");
- diskread(drv,1,4,FAT);
- bogus_clus = dlstoclus(bogus_dls);
- f1 = getFATentry(bogus_clus);
- f2 = getFATentry(bogus_clus+1);
- f3 = getFATentry(bogus_clus+2);
- if (dispflag) {
- printf(" Bogus DLS = %d (%XH)\n",bogus_dls,bogus_dls);
- printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
- bogus_clus,bogus_clus,f1,f1);
- printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
- bogus_clus+1,bogus_clus+1,f2,f2);
- printf(" FAT entry for cluster %d (%xH) = %d (%xH)\n",
- bogus_clus+2,bogus_clus+2,f3,f3);
- }
- if (f1!=0xFF7 || f2!=0xFF7 || f3!=0xFF7) {
- printf("\n This appears to be a partially infected \"Brain\" diskette
- but\n");
- printf(" FAT virus clusters were not all marked as bad.\n");
- printf("\n Aborting cure...\n");
- exit();
- }
-
- /* Get directory table */
- if (dispflag) printf("\nGetting directory entry...\n");
- dirstart = 1 + 4; /* boot sector + FAT size */
- dirsize = 7; /* D-9 diskettes have 7 sectors of dir entries */
- diskread(drv,dirstart,dirsize,directory);
- if (!(bogus_label=findlabel())) {
- printf("\n The Virus label was not found on this diskette!\n");
- }
-
- /* Repair everything */
- printf("\nThis appears to be an infected diskette. \n\n");
- printf(" VACCINATE it (Y/N) ?");
- scanf("%s",ans);
- if (toupper(ans[0])=='Y') {
- printf("\n Inoculating the Drive...\n");
- setFATentry(bogus_clus,0); /* Update FAT */
- setFATentry(bogus_clus+1,0);
- setFATentry(bogus_clus+2,0);
- changelabel(bogus_label);
-
- diskwrite(drv,0,1,orig_bootrec); /* Replace boot rec */
- diskwrite(drv,dirstart,dirsize,directory); /* Write updated direct */
- diskwrite(drv,1,4,FAT); /* Write updated FAT */
- } else {
- printf("\nOK... Aborting!");
- exit();
- }
-
- printf("\n\n Your diskette should now be \"cured\"!\7\n\n");
- if (pc_infected) {
- printf("\nREMEMBER! This PC was infected. Be sure to inoculate\n");
- printf(" the vaccine diskette in case it was infected!\n");
- }
- } /* main */
-
- /********************************************************/
- int checkvec(vec)
- int vec;
- {
- unsigned int vec_ip,vec_cs,orgvec_ip,orgvec_cs,highmem;
- int bad, mem;
-
- bad = 0; /* assume "good" to start */
- vec_ip = peek(4*vec,0); /* check if disk vector was altered */
- vec_cs = peek(4*vec+2,0);
- if (vec_cs < 0xA000) {
- highmem=peek(0x413,0); /* check max mem to allow for "funny", */
- /* legitimate disk drivers */
- for (mem=64,bad=0; mem<=640; mem+=64) {
- if (highmem==(mem-7)) {
- bad=1; /* if max mem value off by 7K => bad */
- break;
- } /* if */
- } /* for */
- } /* if */
- return(bad);
- } /* checkvec */
-
- /********************************************************/
- int copyvec(src,dst)
- int src;
- int dst;
- {
- word vec_ip,vec_cs,highmem;
-
- vec_ip = peek(4*src,0); /* get original vector */
- vec_cs = peek(4*src+2,0);
- pokew(4*dst,0,vec_ip);
- pokew(4*dst+2,0,vec_cs);
- highmem=peek(0x413,0); /* adjust max mem limit while at it */
- highmem += 7; /* get back 7K virus hid in */
- pokew(0x413,0,highmem);
- return;
- } /* copyvec */
- /********************************************************/
- int changelabel(entry)
- int entry;
- {
- int i;
- char *newlabel="Brain Dead ",*p;
-
- for (i=0,p=newlabel; i<11; i++)
- directory[entry].fname[i] = *(p+i);
- directory[entry].attrib = 8;
- for (i=0; i<10; i++) directory[entry].resvd[i] = 0;
- directory[entry].xdate = getdate();
- directory[entry].xtime = gettime();
- directory[entry].startFAT = 0;
- directory[entry].fsize = 0L;
- } /* deletelabel */
-
- /********************************************************/
- int findlabel()
- {
- int i;
-
- for (i=0; i<112; i++) { /* max 112 entries in D-9 disk */
- if (!directory[i].fname[0]) break;
- if ( (directory[i].attrib & 0x08) &&
- (infected(directory[i].fname,0," (c) Brain ")) ) {
- if (!i) { /* label should not be able to be 1st */
- printf("\nThis should not occur! Label First! Abort!\n");
- exit();
- }
- return(i);
- } /* if */
- } /* for */
- return(0);
- } /* findlabel */
-
- /********************************************************/
- word gettime()
- {
- word time;
-
- sreg.ax = 0x2C00;
- sysint21(&sreg,&rreg);
- time = ( ((rreg.cx>>8)<<11) | ((rreg.cx&0xFF)<<5) | (rreg.dx>>9) );
- /* printf("\nch=%d cl=%d dh=%d time=%x\n",
- rreg.cx>>8 , rreg.cx&0xFF, rreg.dx>>8 , time); */
- return(time);
- } /* gettime */
-
- /********************************************************/
- word getdate()
- {
- word idate;
-
- sreg.ax = 0x2A00;
- sysint21(&sreg,&rreg);
- idate = ( ((rreg.cx-1980)<<9) | ((rreg.dx>>8)<<5) | (rreg.dx&0xFF) );
- /* printf("\ncx = %d dx= %x dh= %d dl= %d date= %x \n",
- rreg.cx, rreg.dx, (rreg.dx>>8), (rreg.dx&0xFF), idate); */
- return(idate);
- } /* getdate */
-
- /********************************************************/
- int infected(tgt,pos,src)
- char *tgt;
- int pos;
- char *src;
- {
- char *p,*q;
- int mismatch,len;
-
- len = strlen(src);
- for (mismatch=0,p=tgt+pos,q=src; p<tgt+pos+len && !mismatch; p++,q++)
- mismatch = (*p != *q);
- return(!mismatch);
- } /* infected */
-
- /********************************************************/
- int dlstoclus(dls)
- int dls;
- {
- return(dls/2-4);
- } /* dlstoclus */
-
- /********************************************************/
- int getFATentry(clus)
- int clus;
- {
- int index,entry;
- unsigned int *p;
-
- index = clus*3/2;
- p = &FAT[index];
- entry = (clus%2)? *p >> 4 : *p & 0xFFF;
- return(entry);
- } /* getFATentry */
-
- /********************************************************/
- int setFATentry(clus,val)
- int clus;
- unsigned int val;
- {
- int index,entry; /* On a D-9 diskette, FAT is 4 sectors */
- unsigned int *p;
-
- /* Primary copy of FAT */
- index = clus*3/2; /* 1st 2 sectors of FAT */
- p = &FAT[index];
- *p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
-
- /* Secondary copy of FAT */
- index = clus*3/2 + 512*2; /* Last 2 sectors of FAT */
- p = &FAT[index];
- *p = (clus%2)? (*p & 0xF) | (val << 4) : (*p & 0xF000) | (val & 0xFFF);
-
- return;
- } /* setFATentry */
-
- /********************************************************/
- int errorout(errcode)
- int errcode;
- {
- printf("\n ");
- switch (errcode) {
- case invadr:
- printf("* Invalid disk address format!");
- break;
- case nofixd:
- printf("* This function only applies to Floppy Disk Drives!");
- break;
- default:
- printf("* Unknown Error Encountered!");
- } /* switch */
- printf("\n\n\7");
- } /* errorout */
-
- /********************************************************/
- int diskerror(intrpt, status)
- unsigned int intrpt,status;
- {
- printf("\n ");
- switch (intrpt) {
- case 0x25:
- case 0x26:
- printf("* DOS Disk Read/Write Error!\n");
- printf("\t\tCode = %4x\n",status);
- break;
- case 0x13:
- printf("* ROM-BIOS Disk Read/Write Error!\n");
- printf("\t\tCode = %2x\n",status);
- break;
- } /* switch */
- printf("\n\n\7");
- } /* diskerror */
-
- /********************************************************/
- int diskread(drive, dossectr, nsectrs, buffer)
- int drive, dossectr, nsectrs;
- unsigned char buffer[];
- {
- struct regval rreg,sreg;
- int i;
- unsigned flags;
-
- segread(&segs);
- for (i=0; i<512; i++) buffer[i] = 0;
- sreg.ds = segs.sds;
- sreg.cx = nsectrs;
- sreg.dx = dossectr;
- sreg.bx = buffer;
- sreg.ax = drive-1; /* A=0, B=1 */
- flags = sysint(0x25,&sreg,&rreg);
- if (flags&0x001) diskerror(0x25,rreg.ax);
- return( !(flags&0x001) );
- } /* diskread */
-
- /********************************************************/
- int bdiskread(drive,track,side,sect,nsectrs,buffer)
- int drive, track,side,sect,nsectrs;
- unsigned char buffer[];
- {
- struct regval rreg,sreg;
- int i;
- unsigned flags;
-
- segread(&segs);
- for (i=0; i<512; i++) buffer[i] = 0;
- sreg.es = segs.sds;
- sreg.ax = 0x0200 + nsectrs;
- sreg.cx = (track<<8) + sect;
- sreg.dx = (side<<8) + (drive-1);
- sreg.bx = buffer;
- flags = sysint(0x13,&sreg,&rreg);
- if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
- return( !(flags&0x001) );
- } /* bdiskread */
-
- /********************************************************/
- int diskwrite(drive, dossectr, nsectrs, buffer)
- int drive, dossectr, nsectrs;
- unsigned char buffer[];
- {
- struct regval rreg,sreg;
- int i;
- unsigned flags;
-
- segread(&segs);
- sreg.ds = segs.sds;
- sreg.cx = nsectrs;
- sreg.dx = dossectr;
- sreg.bx = buffer;
- sreg.ax = drive-1; /* A=0, B=1 */
- flags = sysint(0x26,&sreg,&rreg);
- if (flags&0x001) diskerror(0x26,rreg.ax);
- return( !(flags&0x001) );
- } /* diskwrite */
-
- /********************************************************/
- int bdiskwrite(drive,track,side,sect,nsectrs,buffer)
- int drive, track,side,sect,nsectrs;
- unsigned char buffer[];
- {
- struct regval rreg,sreg;
- int i;
- unsigned flags;
-
- segread(&segs);
- sreg.es = segs.sds;
- sreg.ax = 0x0300 + nsectrs;
- sreg.cx = (track<<8) + sect;
- sreg.dx = (side<<8) + (drive-1);
- sreg.bx = buffer;
- flags = sysint(0x13,&sreg,&rreg);
- if (flags&0x001) diskerror(0x13,(rreg.ax>>8) );
- return( !(flags&0x001) );
- } /* bdiskwrite */
-
- /********************************************************/
- int displayraw(buffer,nsectrs)
- unsigned char buffer[];
- int nsectrs;
- {
- int p,i;
- char ascstr[80],ch;
-
- for (i=0; i<(512*nsectrs); i++) {
- if (!(i%16)) {
- if (i) {
- printf("|%s|",ascstr);
- }
- printf("\n%3d: ",i);
- ascstr[p=0] = '\0';
- }
-
- printf("%2x ",buffer[i]);
- ch = (buffer[i]>=' ' && buffer[i]<='~') ? buffer[i] : '.';
- ascstr[p++] = ch;
- ascstr[p] = '\0';
- }
- printf("|%s|",ascstr);
- printf("\n\n");
- } /* displayraw */
-
- /********************************************************/
- int homecursor()
- {
- struct regval rreg,sreg;
-
- sreg.ax = 0x0200; /* cursor position service */
- sreg.bx = 0x0000; /* display page number */
- sreg.dx = 0x0000; /* row and column position */
- sysint(0x10,&sreg,&rreg);
- }
-
- /********************************************************/
- int clearscreen()
- {
- struct regval rreg,sreg;
-
- sreg.ax = 0x0600; /* service plus blank code */
- sreg.bx = 0x0700; /* bh = attrib byte */
- sreg.cx = 0x0000; /* upper left corner of window */
- sreg.dx = (24<<8) + 79; /* lower right corner of window */
- sysint(0x10,&sreg,&rreg);
- homecursor();
- }
-